using System.Net;
using System.Text;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.AspNetCore.Mvc.Filters;
using Publicuse.Cache;
using Publicuse.Entity;
using Publicuse.Interface;
using Publicuse.Util;
using LogClass = Publicuse.Util.LogClass;

namespace Geekeradmin.Filters
{
  public class CustomGlobal : Attribute, IActionFilter, IFilterMetadata, IAuthorizationFilter
  {
    private readonly IMySqlSugarService mySqlSugar;

    private static int resetcount = 0;
    private bool isAllowAnonymous = false;

    public CustomGlobal(IMySqlSugarService mySqlSugar)
    {
      this.mySqlSugar = mySqlSugar;
    }

    public void OnActionExecuted(ActionExecutedContext context) { }

    public void OnActionExecuting(ActionExecutingContext context)
    {
      var queryurl = context.HttpContext.Request.Path; // API请求地址
      var requestmethod = context.HttpContext.Request.Method;
      var checkpass = true;
      if (string.Compare(requestmethod, "GET", true) == 0)
      {
        var querydata = context.HttpContext.Request.QueryString.Value;
        if (!string.IsNullOrEmpty(querydata))
        {
          querydata = querydata.TrimStart('?');
          var getdatalist = JsonUtil.QuerystrToDictionary(querydata);
          var str =
            "'and|exec|insert|select|delete|update|count|*|chr|mid|master|truncate|char|declare|;|+|(|)|（|）|#|@|$|'|>|<|“|”|、|；|!|drop|？|database|version|drop|replace";
          var strlist = str.Split('|');
          foreach (var item in strlist)
          {
            foreach (var itemb in getdatalist)
            {
              var itemvalue = itemb.Value;
              if (!string.IsNullOrEmpty(itemvalue))
              {
                itemvalue = itemvalue.ToLower();
                if (
                  !querydata.Contains("-9")
                  && !queryurl.ToString().ToLower().Contains("delete")
                  && !queryurl.ToString().ToLower().Contains("gettmpotclam")
                  && !queryurl.ToString().ToLower().Contains("exportdata")
                )
                {
                  if (string.Compare(itemvalue, item, true) == 0)
                  {
                    checkpass = false;
                    break;
                  }
                }
              }
            }
            if (!checkpass)
            {
              break;
            }
          }
          if (!checkpass)
          {
            var result = new CommonResult()
            {
              code = (int)ImplementResult.Illegalparameter,
              msg = ImplementResult.Illegalparameter.GetRemark()
            };
            context.Result = new JsonResult(result);
          }
        }
      }
      if (
        string.Compare(requestmethod, "POST", true) == 0
        && string.Compare(queryurl.Value, "/api/Resource/AddOrUpdate", true) != 0
      )
      {
        if (context.HttpContext.Request.ContentType == "application/json")
        {
          Stream straem = context.HttpContext.Request.Body;
          Encoding encoding = Encoding.UTF8;
          string data = string.Empty;
          var reader = new StreamReader(straem, encoding);
          reader.BaseStream.Seek(0, SeekOrigin.Begin);
          var readerStr = reader.ReadToEndAsync().Result;
          reader.BaseStream.Seek(0, SeekOrigin.Begin);
          var postdatalist = JsonUtil.JsonToDictionaryString(readerStr);
          var str =
            "'and|exec|insert|select|delete|update|count|chr|mid|master|truncate|char|declare|database|version|drop|replace";
          var strlist = str.Split('|');
          foreach (var item in strlist)
          {
            foreach (var itemb in postdatalist)
            {
              var itemvalue = itemb.Value;
              if (!string.IsNullOrEmpty(itemvalue))
              {
                itemvalue = itemvalue.ToLower();
                if (string.Compare(itemvalue, item, true) == 0)
                {
                  checkpass = false;
                  break;
                }
              }
            }
            if (!checkpass)
            {
              break;
            }
          }
          if (!checkpass)
          {
            var result = new CommonResult()
            {
              code = (int)ImplementResult.Illegalparameter,
              msg = ImplementResult.Illegalparameter.GetRemark()
            };
            context.Result = new JsonResult(result);
          }
        }
      }
      if (
        string.Compare(queryurl.Value, "/api/Authority/GetVerificationCode", true) != 0
        && string.Compare(queryurl.Value, "/", true) != 0
        && string.Compare(queryurl.Value, "/api/Authority/GetUserVerifyCode", true) != 0
        && string.Compare(queryurl.Value, "/api/Authority/Fail", true) != 0
        && string.Compare(queryurl.Value, "/api/Authority/Login", true) != 0
        && string.Compare(queryurl.Value, "/api/Authority/Logout", true) != 0
        && string.Compare(queryurl.Value, "/api/Authority/NoPage", true) != 0
        && string.Compare(queryurl.Value, "/api/Spconf/GetIndexInfo", true) != 0
        && string.Compare(queryurl.Value, "/api/Home/updatestation", true) != 0
        && string.Compare(queryurl.Value, "/api/User/DownFile", true) != 0
        && string.Compare(queryurl.Value, "/api/User/DownFileb", true) != 0
        && string.Compare(queryurl.Value, "/api/User/Downtaskfile", true) != 0
        && string.Compare(queryurl.Value, "/api/Home/test", true) != 0
        && string.Compare(queryurl.Value, "/api/Home/Index", true) != 0
        && string.Compare(queryurl.Value, "/api/Home/aesmm", true) != 0
        && string.Compare(queryurl.Value, "/api/Generator/Generatordetailednew", true) != 0
        && !queryurl.Value.ToLower().Contains("exportdata")
        && string.Compare(queryurl.Value, "/Vue/Index", true) != 0
      )
      {
        if (context.HttpContext.Request.Headers["token"].Count == 0)
        {
          var result = new CommonResult()
          {
            code = (int)ImplementResult.Nopermissiontooperate,
            msg = ImplementResult.Nopermissiontooperate.GetRemark()
          };
          context.Result = new JsonResult(result);
        }
        else
        {
          var token = context.HttpContext.Request.Headers["token"][0];
          if (!string.IsNullOrEmpty(token))
          {
            token = token.Replace("Bearer ", "");
          }
          JwtToken jwttoken = new JwtToken();
          LoginCache.GetLoginCache.GetJwtToken(token, out jwttoken);
          var isTimeout = LoginCache.GetLoginCache.isTimeout(token, jwttoken);
          if (isTimeout)
          {
            var result = new CommonResult()
            {
              code = (int)ImplementResult.UserLoginTimeOut,
              msg = ImplementResult.UserLoginTimeOut.GetRemark()
            };
            context.Result = new JsonResult(result);
          }
          else
          {
            var signinInfo = TableAtributeUtil.GetTable<SigninInfo>();
            var sql = $"select * from {signinInfo} where loginid='{token}';";
            var qddata = this.mySqlSugar.Query<SigninInfo>(sql, out var msg);
            if (string.IsNullOrEmpty(msg) && qddata != null && qddata.Count > 0)
            {
              var signindata = qddata.FirstOrDefault();
              signindata.uTime = DateTime.Now;
              this.mySqlSugar.Update<SigninInfo>(signindata, out msg);
            }
            var headers = context.HttpContext.Request.Headers;
            var querytype = context.HttpContext.Request.Method; // 请求方式
            var querydata = string.Empty; // 请求参数
            var queryheader = context.HttpContext.Request.Headers.ToList();
            var loginUserCode = HttpContextExtendBase.GetLoginCode();
            if (string.Compare(queryurl.Value, "/api/User/DownFile", true) == 0)
            {
              loginUserCode = HttpContextExtendBase.GetLoginCode(token);
            }
            if (string.IsNullOrEmpty(loginUserCode))
            {
              var result = new CommonResult()
              {
                code = (int)ImplementResult.Nopermissiontooperate,
                msg = ImplementResult.Nopermissiontooperate.GetRemark()
              };
              context.Result = new JsonResult(result);
            }
            var loginToken = string.Empty;
            var browserinfo = string.Empty;
            headers.TryGetValue("User-Agent", out var browser);
            if (!string.IsNullOrEmpty(browser))
            {
              browserinfo = browser.ToString();
            }

            var Haveauthority = LoginCache.GetLoginCache.HaveMenu(loginUserCode, queryurl);
            if (!Haveauthority && !isAllowAnonymous)
            {
              var result = new CommonResult()
              {
                code = (int)ImplementResult.Nopermissiontooperate,
                msg = ImplementResult.Nopermissiontooperate.GetRemark()
              };
              context.Result = new JsonResult(result);
            }
            else
            {
              if (headers.ContainsKey("X-Forwarded-For"))
              {
                HttpContextExtendBase.Current.Connection.RemoteIpAddress = IPAddress.Parse(
                  headers["X-Forwarded-For"]
                    .ToString()
                    .Split(',', StringSplitOptions.RemoveEmptyEntries)[0]
                );
              }
              var remoteIp =
                LogClass.GetIPAddress()
                + "|"
                + headers["X-Real-IP"].ToString()
                + "|"
                + headers["X-Forwarded-For"].ToString();
              if (string.Compare(remoteIp, "::1", true) == 0)
              {
                remoteIp = HttpContextExtendBase
                  .Current.Connection.LocalIpAddress.MapToIPv4()
                  ?.ToString();
              }
              if (remoteIp.Split(':').Length >= 3)
              {
                remoteIp = remoteIp.Split(':')[3];
              }
              var RemoteIpAddress = HttpContextExtendBase.Current.Connection.RemoteIpAddress;
              var ipaddress = $"{remoteIp + "|" + RemoteIpAddress}";
              if (
                !queryurl.Value.ToLower().Contains("import")
                && !queryurl.Value.ToLower().Contains("upload")
                && !queryurl.Value.ToLower().Contains("getfilepath")
              )
              {
                querydata = context.HttpContext.GetParams(); // 请求参数
              }
              else
              {
                querydata = "导入/上传文件数据";
              }
              var content =
                "请求IP【"
                + ipaddress
                + "】，请求类型【"
                + querytype
                + "】，请求接口【"
                + queryurl
                + "】，请求参数【"
                + querydata
                + "】，请求头【"
                + JsonUtil.ToJson(queryheader)
                + "】";
              Log log = new Log()
              {
                lmodule = "访问IP统计",
                ltype = querytype,
                luser = HttpContextExtendBase.GetLoginCode(),
                lsuccess = 1,
                status = 1,
                lrole = HttpContextExtendBase.GetLoginrName(),
                lcontent = content
              };
              if (
                string.Compare(queryurl, "/api/Log/GetLogList", true) != 0
                && string.Compare(queryurl, "/api/Log/GetLogListb", true) != 0
                && string.Compare(queryurl, "/api/Log/GetLogListc", true) != 0
                && string.Compare(queryurl, "/api/Log/GetLogListd", true) != 0
                && string.Compare(queryurl, "/api/Log/GetLogListe", true) != 0
              )
              {
                //this.mySqlSugar.Insert<Log>(log, out msg);
              }
              //LogUtil.GetInstance.WriteLogOld("访问IP统计-" + remoteIp + "-" + querytype, content, true);
            }
          }
        }
      }
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
      //判断是否跳过受权过滤器
      isAllowAnonymous = HasAllowAnonymous(context);
    }

    private bool HasAllowAnonymous(AuthorizationFilterContext context)
    {
      var filters = context.Filters;
      for (int i = 0; i < filters.Count; i++)
      {
        if (filters[i] is IAllowAnonymousFilter)
        {
          return true;
        }
      }
      var endpoint = context.HttpContext.GetEndpoint();
      if (endpoint?.Metadata?.GetMetadata<IAllowAnonymous>() != null)
      {
        return true;
      }
      return false;
    }
  }
}
